﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IrisGenerator.Common.Modules;
using IrisGenerator.Framework.Events;
using IrisGenerator.Common.DatabaseModel;
using System.Data.SqlClient;
using IrisGenerator.Modules.SqlServer2005.DataAccess;
using IrisGenerator.Framework.Database;
using IrisGenerator.Common.DataTypes;
using IrisGenerator.Common.Core;
using IrisGenerator.Modules.SqlServer2005.SqlModel;

namespace IrisGenerator.Modules.SqlServer2005.Analyzers
{
    [ModuleName("SqlServer 2005 Analyzer")]
    [ModuleDescription("This module analyzes the structure of an Sql Server 2005 database.")]
    [ModuleVersion(0,1)]
    [ModuleTarget("SQL2005","Sql Server 2005","A module that targets Sql Server 2005 databases.")]
    public class DbAnalyzer:ModuleBase
    {

        [ModuleParameter("ConnectionString", "System.String", true, ModuleParameterDirection.InOut)]
        public string ConnectionString { get; set; }

        [ModuleParameter("Database", "IrisGenerator.Common.DatabaseModel.Database", false, ModuleParameterDirection.Output)]
        public Database Database { get; set; }

        public override bool Analyse()
        {
            this.OnAnalyseProgress(
                new ProgressEventArgs<ModuleBase>
                (this, 0, "Starting Analyse"));

            this.OnStartingAnalyse(
                new BaseEventArgs<ModuleBase>
                (this, false));

            this.ConnectionString = @"server=localhost\sqlexpress;database=IrisGenerator;integrated security=sspi;";

            if (string.IsNullOrEmpty(this.ConnectionString))
                throw new ArgumentException("The connection string must be defined.");

            //Common.Data.MetaType.LoadEquivalences("SQLServer2005");

            //DatabaseCollection databases = Database.GetAll();


            //Try to get database if there are some instances...

            SetDatabase();
            //if (!this.ModInsId.HasValue)
            //    SetDatabase();
            //else
            //    LoadDatabase();

            GetTables();

            GetPrimaryKeys();
            GetForeignKeys();

            
            


            //this.Database.TableCollection

            //this.OnProgress(new Iris.Common.Events.ProgressEventArgs(0,
            //    Resource.GetString("Iris.Modules.SqlServer2005.DatabaseAnalyzers.DBAnalyzer.GettingTables")));

            ////TODO: Cette méthode met beaucoup de temps à s'éxectuer !!
            //_database.Tables.CleanAndFill(GetTables(_database, ConnectionString));

            //this.OnProgress(new Iris.Common.Events.ProgressEventArgs(10));

            //if (_database.Tables.Count > 0)
            //{
            //    double unitProgress = 90.0 / ((double)_database.Tables.Count * 2.0);
            //    int globalProgress = 10;

            //    foreach (ir.ITableKind t in _database.Tables)
            //    {

            //        this.OnProgress(new Iris.Common.Events.ProgressEventArgs(globalProgress,
            //            Resource.GetString("Iris.Modules.SqlServer2005.DatabaseAnalyzers.DBAnalyzer.AnalyzingTable", t.Name)));

            //        ColumnCollection columns = GetColumns(t, ConnectionString);

            //        if (columns != null)
            //            t.Columns.CleanAndFill(columns);

            //        ir.Table table = t as ir.Table;
            //        if (table != null)
            //        {
            //            ir.Constraint primaryKey = GetPrimaryKey(table, ConnectionString);

            //            if (primaryKey != null)
            //            {
            //                table.Constraints.Add(primaryKey);
            //                if (primaryKey.Keys.Count == 1 && primaryKey.Keys[0].PrimaryKey.MetaType.Equals("GUID"))
            //                    primaryKey.Keys[0].PrimaryKey.AutoField = ir.ColumnAutoField.OnInsert;
            //            }
            //        }

            //        globalProgress += (int)unitProgress;

            //        this.OnProgress(new Iris.Common.Events.ProgressEventArgs(globalProgress));
            //    }


            //    foreach (ir.ITableKind t in _database.Tables)
            //    {
            //        this.OnProgress(new Iris.Common.Events.ProgressEventArgs(globalProgress,
            //            Resource.GetString("Iris.Modules.SqlServer2005.DatabaseAnalyzers.DBAnalyzer.AnalyzingTable", t.Name)));

            //        ir.Table table = t as ir.Table;
            //        if (table != null)
            //            GetForeignKeys(table, ConnectionString);

            //        globalProgress += (int)unitProgress;
            //        this.OnProgress(new Iris.Common.Events.ProgressEventArgs(globalProgress));
            //    }
            //}
            //this.OnProgress(new Iris.Common.Events.ProgressEventArgs(100));
            //return _database;

            return true;
        }

        private void LoadDatabase()
        {
            
        }

        private void GetForeignKeys()
        {
            if (this.Database == null)
                return;

            foreach (Table table in this.Database.TableCollection)
            {
                SqlTable.GetForeignKeys(table, this.ConnectionString);
            }
        }

        private void GetPrimaryKeys()
        {
            if (this.Database == null)
                return;

            foreach (Table table in this.Database.TableCollection)
            {
                SqlTable.GetTablePrimaryKey(table, this.ConnectionString);
            }
            
        }

        public override bool Generate()
        {
            return true;
        }

        #region Database Analyze

        private void SetDatabase()
        {
            //TODO: The database should never be null

            if (this.ParametersInstances.ContainsKey("Database"))
            {
                Guid? id = this.ParametersInstances["Database"].ModParInsValue;
                if (!id.HasValue)
                {
                    this.Database = new Database();
                    this.Database.DbName = "MyDBTest";
                    this.Database.DbId = this.Database.Insert();

                    this.ParametersInstances["Database"].ModParInsValue = this.Database.DbId;
                    if (this.ParametersInstances["Database"].ModParInsId.HasValue)
                    {
                        this.ParametersInstances["Database"].Update();
                    }
                    else
                    {
                        this.ParametersInstances["Database"].Insert();
                    }
                }
                else
                {
                    this.Database = Database.Load(id);
                    if (this.Database == null)
                    {
                        this.Database = new Database();
                        this.Database.DbName = "MyDBTest";
                        this.Database.DbId = this.Database.Insert();
                        this.ParametersInstances["Database"].ModParInsValue = this.Database.DbId;
                        if (this.ParametersInstances["Database"].ModParInsId.HasValue)
                        {
                            this.ParametersInstances["Database"].Update();
                        }
                        else
                        {
                            this.ParametersInstances["Database"].Insert();
                        }
                    }
                }
            }
            else
            {
                throw new ApplicationException("The database parameter is not defined");
            }
        }

        private TableCollection GetTables()
        {
            TableCollection FoundTables = SqlDatabase.GetTables(this.ConnectionString);

            //TODO: Compare with existing tables...
            for (int i = 0; i < FoundTables.Count; i++)
            {
                Table CurrentTable = this.Database.TableCollection.Exists(FoundTables[i]);
                
                if (CurrentTable != null)
                {
                    FoundTables[i] = CurrentTable;
                    CurrentTable.TabIsView = false;
                    CurrentTable.Database = this.Database;
                    
                    CurrentTable.Update();
                }
                else
                {
                    CurrentTable = FoundTables[i];
                    CurrentTable.Database = this.Database;
                    CurrentTable.TabIsView = false;
                    CurrentTable.Insert();
                }

                GetColumns(CurrentTable);
                this.Database.TableCollection.Add(CurrentTable);
            }

            return FoundTables;
        }

        private void GetColumns(Table table)
        {
            ColumnCollection FoundColumns = SqlTable.GetColumns(table,this.ConnectionString);

            for (int i = 0; i < FoundColumns.Count; i++)
            {
                Column CurrentColumn = table.ColumnCollection.Exists(FoundColumns[i]);

                if (CurrentColumn != null)
                {
                    CurrentColumn = FoundColumns[i];
                    //CurrentColumn.TabIsView = false;
                    //CurrentColumn.Database = this.Database;
                    CurrentColumn.Update();
                }
                else
                {
                    CurrentColumn = FoundColumns[i];
                    //CurrentColumn.Database = this.Database;
                    //CurrentColumn.TabIsView = false;
                    table.ColumnCollection.Add(CurrentColumn);
                    CurrentColumn.Insert();
                }
            }


        }

        

        #endregion
    }
}
